home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2001 / MacHack 2001.toast / pc / The Hacks / The Weakest Link / source / SortFrames.cp < prev    next >
Encoding:
Text File  |  2001-06-23  |  10.8 KB  |  424 lines

  1. #ifdef PowerPlant_PCH
  2.     #include PowerPlant_PCH
  3. #endif
  4.  
  5. #include <LString.h>
  6. #include <PP_Resources.h>
  7.  
  8. #include <PP_Types.h>
  9. #include <PP_Constants.h>
  10. #include <stdio.h>
  11. #include <MacMemory.h>
  12. #include <OpenTransport.h>
  13. #include <OpenTransportProviders.h>
  14. #include <string.h>
  15.  
  16. #include "IPTypes.h"
  17. #include "SortFrames.h"
  18. #include "myDns.h"
  19.  
  20. extern bool gAllDomains;
  21.  
  22. #define USE_UDP        1
  23.  
  24. // relium is: 216.92.237.137
  25. const UInt32 kMagicReliumAddress = 0xD85CED89;
  26.  
  27. // 209.153.140.221
  28. const UInt32 kMagicIPAddress = 0xD1998CDD;
  29.  
  30. int BuildResponse( msg_descriptor_t *md, unsigned char *outputBuffer );
  31. Boolean PutDName(msg_descriptor_t* md, ConstStr255Param inStr);
  32. int SendDNSResponse( unsigned char *outputBuffer, UInt32 bytesToWrite );
  33. void ConvertIPToName( UInt32 ip, char *ipname );
  34. void CopyPtoC( const unsigned char *, char * );
  35.  
  36. void ConsumePacket( Packet *packet, UInt32 inSize )
  37. {
  38. //    if( packet->protocol != 6 ) goto toss; // only TCP packets please
  39. //    if( ( packet->versionAndIHL & 0x0f ) != 5 ) goto toss; // minimal IP headers only (lame?)
  40.  
  41.     if ( (packet->protocol != 17) || (packet->dstPort != 53) )
  42.         return;
  43.  
  44.     if ( packet->messageLength < 0 /* ??? */ )
  45.         return;
  46.  
  47.     char                ipname[64];
  48.     
  49.     ConvertIPToName( packet->sourceIP, ipname );
  50.         
  51.     printf("DNS Request from %s (port %u)\n", ipname, packet->srcPort );
  52.  
  53.     dns_request_t        dnsRequest, *inRequest = &dnsRequest;
  54.     msg_descriptor_t*    md = &dnsRequest.md;
  55.     dns_header_t*        dnsHeader;
  56.     UInt16                qType, qClass;
  57.     Str255                qName;
  58.     unsigned char        outputBuffer[ 1500 ];
  59.     
  60.     dnsRequest.md.data = (unsigned char*) packet;
  61.     dnsRequest.md.size = inSize;
  62.  
  63.     dnsHeader = (dns_header_t*)packet->data;
  64.     dnsRequest.md.offset = 28;
  65.     
  66.     do {
  67.         // ignore responses
  68.         if (dnsHeader->queryParameter & kQueryMaskQR) break;
  69.         // make sure there is a question
  70.         if (dnsHeader->QDCount == 0) break;
  71.         // skip header
  72.         md->offset = 40;        // 12 + 28
  73.         // get the query name
  74.         GetDName(md, qName);
  75.         // get query type and class
  76.         ::BlockMoveData(&((unsigned char*)packet)[md->offset], &qType, 2);
  77.         ::BlockMoveData(&((unsigned char*)packet)[md->offset+2], &qClass, 2);
  78.  
  79.         // if query is a simple name lookup
  80.         if ((qClass == kQClassIN) && (qType == kQTypeA)) 
  81.         {
  82.             printf("DNS Request from %s (port %u): %#s\n", ipname, packet->srcPort, qName );
  83.             
  84.             #if 0
  85.             if ( EqualString( "\pwoz.com", qName, false, false ) ||
  86.                  EqualString( "\pwww.woz.com", qName, false, false ) ||
  87.                  EqualString( "\pwoz.org", qName, false, false ) ||
  88.                  EqualString( "\pwww.woz.org", qName, false, false ) )
  89.             #endif
  90.             
  91.             bool        sendIt = false;
  92.             char        tempCString[256];
  93.             
  94.             if ( gAllDomains )
  95.                 sendIt = true;
  96.             
  97.             if ( !sendIt )
  98.                 sendIt = 
  99.                  ( (qName[0] > 3) &&
  100.                  ( (qName[1] == 'w') || (qName[1] == 'W')) &&
  101.                  ( (qName[2] == 'w') || (qName[2] == 'W')) &&
  102.                  ( (qName[3] == 'w') || (qName[3] == 'W')) );
  103.  
  104.             if ( !sendIt )
  105.             {
  106.                 CopyPtoC( qName, tempCString );
  107.                 if ( strstr( tempCString, "doubleclick.com" ) )
  108.                     sendIt = true;
  109.                 if ( strstr( tempCString, "doubleclick.net" ) )
  110.                     sendIt = true;
  111.                 if ( strstr( tempCString, "x10.com" ) )
  112.                     sendIt = true;
  113.             }
  114.             
  115.             if ( sendIt )
  116.             {
  117.                 int bytesToWrite = BuildResponse( md, outputBuffer );
  118.                 
  119.                 int err = SendDNSResponse( outputBuffer, bytesToWrite );
  120.                 if ( err )
  121.                     printf("Error sending response %d\n", err );
  122.             }
  123.         }
  124.         else if ((qClass == kQClassIN) && (qType == kQTypePTR)) 
  125.         {
  126.             //isTypePTR = true;
  127.         }                
  128.     } while (false);
  129. }
  130.  
  131. int BuildResponse( msg_descriptor_t *md, unsigned char *outputBuffer )
  132. {
  133.     UInt16        param;
  134.     UInt16        dataOffset = 28;
  135.     Str255        qName;
  136.     UInt32        theAddress = kMagicIPAddress;
  137.     msg_descriptor_t    outputMD;
  138.     
  139.     ::BlockMoveData( md->data, outputBuffer, md->size );
  140.     outputMD.data = outputBuffer;
  141.     outputMD.size = 1400;
  142.     outputMD.offset = md->offset;
  143.     
  144.     // build response
  145.         // we start with the original query
  146.         // set parameter to indicate a response
  147.     param = kQueryMaskQR;
  148.     ::BlockMoveData(¶m, &outputMD.data[dataOffset+2], 2);
  149.         // indicate 1 answer
  150.     param = 1;
  151.     ::BlockMove(¶m, &outputMD.data[dataOffset+6], 2);
  152.     // we leave the question as received
  153.     // get query name
  154.     outputMD.offset = dataOffset+12;    // start of question
  155.     (void) GetDName(&outputMD, qName);
  156.     outputMD.offset += 4; // skip the qType and qClass
  157.     
  158.     // now we're ready to start loading our answer
  159.  
  160.     // repeat the query name as the resource owner
  161.     PutDName(&outputMD, qName);
  162.  
  163.     // continue filling in answer Resource Record
  164.     dns_record_t* rr;
  165.     rr = (dns_record_t*)&outputMD.data[outputMD.offset];
  166.     rr->rdType =  kQTypeA;
  167.     rr->rdClass = kQClassIN;
  168.     rr->rdTTL = 1;
  169.     rr->rdLength = 4;
  170.     outputMD.offset += 10;
  171.         // write our address response
  172.     ::BlockMoveData(&theAddress, &outputMD.data[outputMD.offset], 4);
  173.     outputMD.offset += 4;
  174.         // set message length
  175.     outputMD.size = outputMD.offset;        
  176.     
  177.     return outputMD.size;
  178. }
  179.  
  180. // ---------------------------------------------------------------------------
  181. //        • GetDName
  182. // ---------------------------------------------------------------------------
  183. //    Convert a sequence of labels in Name Server format to a name string
  184. //        Return false if name exceeds maximum length (255)
  185. //        or contains an invalid pointer.
  186. Boolean GetDName(msg_descriptor_t* md, Str255 outStr)
  187. {
  188.     LStr255    name;
  189.     Str255    label;
  190.     UInt8    len;
  191.     UInt16    offset, pointer, oldPointer, nameLength;
  192.     UInt16*    dp;
  193.     Boolean    isPointer;
  194.  
  195.     name = "\p";    // initialize name
  196.     nameLength = 0;
  197.     offset = md->offset;
  198.     isPointer = false;
  199.  
  200.     len = md->data[offset];    
  201.     // copy each label until end of name indicated by 0
  202.     while (len) {
  203.         // is it a pointer?
  204.         if (len >= 64) {
  205.             // yes, get pointer
  206.             if (!isPointer) {
  207.                 dp = (UInt16*)&md->data[offset];    // cast to 16-bit quantity
  208.                 offset += 2;            // advance current offset past pointer
  209.             } else {
  210.                 dp = (UInt16*)&md->data[pointer];    // cast to 16-bit quantity
  211.             }
  212.             oldPointer = pointer;
  213.             pointer = dp[0] & 0x3FFF;    // get new pointer
  214.             // pointers must refer to a prior occurance of the same name
  215.             // reject garbage pointers and pointer loops (defensive)
  216.             if (!isPointer && (pointer >= offset)) return false;
  217.             if (isPointer && (pointer >= oldPointer)) return false;
  218.             isPointer = true;
  219.         } else {
  220.             // no, copy label
  221.             if (!isPointer) {
  222.                 LString::CopyPStr(&md->data[offset], label, 64);
  223.                 offset += len + 1;    // advance offset past label
  224.             } else {
  225.                 LString::CopyPStr(&md->data[pointer], label, 64);
  226.                 pointer += len + 1;    // advance pointer past label            
  227.             }
  228.             // add label to name
  229.             name += label;
  230.             name += "\p.";    // append a dot
  231.             // check for valid length (defensive)
  232.             nameLength += len + 1;
  233.             if (nameLength > 255) return false;
  234.         }
  235.         // prepare to get next label
  236.         if (!isPointer) len = md->data[offset];
  237.         else len = md->data[pointer];
  238.     }
  239.     // if not a pointer, skip terminating zero
  240.     if (!isPointer) offset += 1;
  241.     // update ioOffset
  242.     md->offset = offset;
  243.     
  244.     // remove final dot from end of name
  245.     len = name.Length();
  246.     if (len != 0) name.Remove(len, 1);
  247.     // return the resulting name
  248.     LString::CopyPStr(name, outStr, 255);
  249.     return true;
  250. }
  251.  
  252. // ---------------------------------------------------------------------------
  253. //        • PutDName
  254. // ---------------------------------------------------------------------------
  255. //    Write a domain name in Name Server format
  256. //    as a sequence of labels.
  257. //    Return false if name won't fit in message.
  258. Boolean PutDName(msg_descriptor_t* md, ConstStr255Param inStr)
  259. {
  260.     LStr255 name, label;
  261.     UInt8 start, pos;
  262.     UInt16 offset;
  263.     UInt8* inMessage;
  264.     
  265.     inMessage = md->data;
  266.     name = inStr;
  267.     offset = md->offset;
  268.     // copy each segment separated by '.' as a PString
  269.     start = 1;
  270.     pos = name.Find('.', start);
  271.     while (pos != 0) {
  272.         label.Assign(name, start, pos-start);
  273.         if ((label.Length() + offset) >= md->size) return false;
  274.         LString::CopyPStr(label, &inMessage[offset]);
  275.         offset += pos-start + 1;
  276.         start = pos + 1;
  277.         pos = name.Find('.', start);
  278.     }
  279.     // get last segment
  280.     label.Assign(name, start);
  281.     if ((label.Length() + offset) >= (md->size-1)) return false;
  282.     LString::CopyPStr(label, &inMessage[offset]);
  283.     offset += label[0] + 1;    // adjust offset to include length
  284.     // mark the end if necessary
  285.     if (label[0] != 0) {
  286.         inMessage[offset] = 0;
  287.         offset += 1;
  288.     }
  289.     
  290.     // set new offset
  291.     md->offset = offset;
  292.     return true;
  293. }
  294.  
  295. EndpointRef        gEndpoint;
  296. bool            gEndpointOpen = false;
  297.  
  298. int InitializeResponses()
  299. {
  300.     long                err = 0;
  301.     TEndpointInfo        endpointInfo;
  302.     
  303.     if ( gEndpointOpen ) return(0);
  304.  
  305. #ifdef USE_UDP
  306.     gEndpoint = ::OTOpenEndpoint( ::OTCreateConfiguration(kUDPName), 0, &endpointInfo, &err );
  307. #else
  308.     gEndpoint = ::OTOpenEndpoint( ::OTCreateConfiguration(kRawIPName), 0, &endpointInfo, &err );
  309. #endif
  310.  
  311.     if ( err ) return( err );
  312.     gEndpointOpen = true;
  313.     
  314.     TBind            reqAddr, retAddr;
  315.     InetAddress        addr, addr2;
  316.     
  317.     addr.fAddressType = AF_INET;
  318.     addr.fPort = 53;
  319.     addr.fHost = 0;
  320. //    addr.fUnused = ;
  321.     
  322.     reqAddr.addr.maxlen = sizeof(InetAddress);
  323.     reqAddr.addr.len = sizeof(InetAddress);;
  324.     reqAddr.addr.buf = (unsigned char*) &addr;
  325.     reqAddr.qlen = 0;
  326.     
  327.     retAddr.addr.maxlen = sizeof(InetAddress);
  328.     retAddr.addr.len = sizeof(InetAddress);
  329.     retAddr.addr.buf = (unsigned char*) &addr2;
  330.     retAddr.qlen = 0;
  331.  
  332.     err = ::OTBind( gEndpoint, &reqAddr, &retAddr );
  333.     if ( err ) return( err );
  334.  
  335. #ifndef USE_UDP    
  336.         // set to raw mode
  337.     TOptMgmt    req;
  338.     TOption*    opt;
  339.     UInt8        OptionBuf[ kOTFourByteOptionSize ];
  340.     
  341.     opt = (TOption*) OptionBuf;
  342.     req.opt.buf = OptionBuf;
  343.     req.opt.len = sizeof(OptionBuf);
  344.     req.opt.maxlen = sizeof(OptionBuf);
  345.     req.flags = T_NEGOTIATE;
  346.     
  347.     opt->level = INET_IP;
  348.     opt->name = 255;            // IPPROTO_RAW (per docs)
  349.     opt->len = kOTFourByteOptionSize;
  350.     *(UInt32*)opt->value = true;
  351.     
  352.     err = ::OTOptionManagement(gEndpoint, &req, &req );
  353. #endif
  354.  
  355.     return( err );
  356. }
  357.  
  358. void CleanupResponses()
  359. {
  360.     if ( gEndpointOpen )
  361.     {
  362.         gEndpointOpen = false;
  363.         ::OTCloseProvider( gEndpoint );
  364.     }
  365. }
  366.  
  367. int SendDNSResponse( unsigned char *outputBuffer, UInt32 bytesToWrite )
  368. {
  369.     Packet *p = (Packet*) outputBuffer;
  370.     int        err = 0;
  371.     
  372.     printf("Sending DNS Reponse.\n\n");
  373.     
  374.     // swap source/dest IP addresses
  375.     UInt32    temp = p->sourceIP;
  376.     p->sourceIP = p->destIP;
  377.     p->destIP = temp;
  378.     p->messageLength = bytesToWrite;
  379.     
  380.     // swap source/dest ports
  381.     p->dstPort = p->srcPort;
  382.     p->srcPort = 53;
  383.     
  384.     TUnitData        data;
  385.     InetAddress        destAddr;
  386.     
  387.     destAddr.fAddressType = AF_INET;
  388.     destAddr.fHost = p->destIP;
  389.     destAddr.fPort = p->dstPort;
  390.     //destAddr.fUnused;
  391.     
  392.     data.addr.maxlen = sizeof(InetAddress);
  393.     data.addr.len = sizeof(InetAddress);
  394.     data.addr.buf = (unsigned char*) &destAddr;
  395.     data.opt.maxlen = 0;
  396.     data.opt.len = 0;
  397.     data.opt.buf = 0;
  398.     data.udata.maxlen = bytesToWrite;
  399.     data.udata.len = bytesToWrite;
  400.     
  401.     #ifdef USE_UDP
  402.     data.udata.buf = 28 + (unsigned char*)outputBuffer;
  403.     #else
  404.     data.udata.buf = (unsigned char*)outputBuffer;
  405.     #endif
  406.     
  407.     err = OTSndUData( gEndpoint, &data );
  408.     return( err );
  409. }
  410.  
  411.  
  412.  
  413. void ConvertIPToName( UInt32 ip, char *ipname )
  414. {
  415.     unsigned char *p = (unsigned char*) &ip;
  416.     sprintf( ipname, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
  417. }
  418.  
  419. void CopyPtoC( const unsigned char *src, char *dst )
  420. {
  421.     BlockMoveData( src+1, dst, *src );
  422.     dst[*src] = 0;
  423. }
  424.